package common.stack.delayStack.one;

import common.stack.delayStack.DelayedStack;

public class MyStack<E> implements DelayedStack<E> {

    private E[] array;
    private int size;
    private int maximumDelay;
    private int delayCount;
    private boolean allowPop;
    private boolean hasPop;

    public MyStack(int maximumDelay) {
        this.maximumDelay = maximumDelay;

        this.array = (E[]) new Object[10];
        this.size = 0;
        this.delayCount = maximumDelay;
        this.allowPop = false;
        this.hasPop = false;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public void push(E element) {
        if (size == array.length) {
            E[] newArray = (E[]) new Object[size * 2];
            System.arraycopy(array, 0, newArray, 0, size);
            array = newArray;
        }

        array[size++] = element;

        if (allowPop && hasPop) {
            delayCount = maximumDelay;
            hasPop = false;
        }

        delayCount--;
        allowPop = delayCount <= 0;
    }

    @Override
    public E pop() throws IllegalStateException {
        if (size == 0) {
            throw new IllegalStateException();
        } else if (!allowPop) {
            return null;
        }

        size--;
        E data = array[size];
        array[size] = null;
        hasPop = true;

        return data;
    }

    @Override
    public E peek() throws IllegalStateException {
        if (size == 0) {
            throw new IllegalStateException();
        }
        return array[size - 1];
    }

    @Override
    public int getDelay() {
        if (allowPop) {
            return 0;
        }
        return delayCount <= 0 ? 0 : delayCount;
    }

    @Override
    public void setMaximumDelay(int d) {
        this.maximumDelay = d;
    }

    @Override
    public int getMaximumDelay() {
        return maximumDelay;
    }

    @Override
    public boolean clear() {
        if (allowPop) {
            this.array = (E[]) new Object[10];
            this.size = 0;
            this.hasPop = true;
            return true;
        }
        return false;
    }

    @Override
    public boolean contains(E elem) {
        for (int i = 0; i < size; i++) {
            if ((array[i] == null && elem == null)
                    || (array[i] != null && array[i].equals(elem))) {
                return true;
            }
        }
        return false;
    }
}